package com.bristua.barcode.job;

import com.bristua.barcode.common.bean.Result;
import com.bristua.barcode.common.code.Api;
import com.bristua.barcode.common.code.ImagePreProcess;
import com.bristua.barcode.common.code.Util;
import com.bristua.barcode.common.config.VerificationCodeConfig;
import com.bristua.barcode.common.constants.Constants;
import com.bristua.barcode.common.util.*;
import com.bristua.barcode.customer.biz.GetCustomerBindQRCodeBiz;
import com.bristua.barcode.customer.biz.UpdateCustomerAccountBiz;
import com.bristua.barcode.customer.dao.TCustomerBindSupplierMapper;
import com.bristua.barcode.customer.dao.TCustomerMapper;
import com.bristua.barcode.customer.model.TCustomer;
import com.bristua.barcode.customer.model.TCustomerBindSupplier;
import com.bristua.barcode.customer.model.bo.CustomerBindQRCode;
import com.bristua.barcode.customer.model.condition.TCustomerBindSupplierExample;
import com.bristua.barcode.customer.model.condition.TCustomerExample;
import com.bristua.barcode.job.bo.StandardOrder;
import com.bristua.barcode.order.dao.TCallbackMsgMapper;
import com.bristua.barcode.order.dao.TOrderFlowMapper;
import com.bristua.barcode.order.dao.TPayOrderMapper;
import com.bristua.barcode.order.model.TCallbackMsg;
import com.bristua.barcode.order.model.TOrderFlow;
import com.bristua.barcode.order.model.TPayOrder;
import com.bristua.barcode.order.model.bo.LakalaOrder;
import com.bristua.barcode.order.model.condition.TCallbackMsgExample;
import com.bristua.barcode.supplier.dao.TChannelMapper;
import com.bristua.barcode.supplier.dao.TQrCodeLimitAmtAdjustmentMapper;
import com.bristua.barcode.supplier.dao.TQrCodeMapper;
import com.bristua.barcode.supplier.dao.TSupplierMapper;
import com.bristua.barcode.supplier.model.TChannel;
import com.bristua.barcode.supplier.model.TQrCode;
import com.bristua.barcode.supplier.model.TQrCodeLimitAmtAdjustment;
import io.swagger.models.auth.In;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by Administrator on 2019/8/11 0011.
 */
@Service
@Transactional
public class HandelOrderJob {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private VerificationCodeConfig verificationCodeConfig;

    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private TPayOrderMapper tPayOrderMapper;

    @Resource
    private TCustomerBindSupplierMapper tCustomerBindSupplierMapper;

    @Resource
    private TCustomerMapper tCustomerMapper;

    @Resource
    private TQrCodeMapper tQrCodeMapper;

    @Resource
    private TSupplierMapper tSupplierMapper;

    @Autowired
    private GetCustomerBindQRCodeBiz getCustomerBindQRCodeBiz;

    @Resource
    private TQrCodeLimitAmtAdjustmentMapper tQrCodeLimitAmtAdjustmentMapper;

    @Resource
    private TOrderFlowMapper tOrderFlowMapper;

    @Resource
    private TCallbackMsgMapper tCallbackMsgMapper;

    @Autowired
    private UpdateCustomerAccountBiz updateCustomerAccountBiz;

    @Resource
    private TChannelMapper tChannelMapper;


    //@TODO 不要忘记配置回调url
    private static final String callbackUrl = "";

    @Scheduled(cron = "0/10 * * * * ?")
    public void handelOrder() {
        Set members = redisTemplate.opsForSet().members(Constants.NO_PAY_ORDER_SET);
        if (members != null && members.size() > 0) {
            //先取100个订单出来
            asyncHandelOrder(redisTemplate.opsForSet().pop(Constants.NO_PAY_ORDER_SET, 100));
        }
    }

    @Async
    public void callbackOrder(String orderId, String appId, String secretKey, String flowNo) {
        TPayOrder tPayOrder = tPayOrderMapper.selectByPrimaryKey(orderId);
        logger.info("==>正在准备回调给商户:" + JsonUtil.toJson(tPayOrder));
        StringBuilder sign = new StringBuilder();
        sign.append(appId).append(tPayOrder.getCustomerOrderNo()).append(tPayOrder.getPayAmt()).append(tPayOrder.getPayStatus()).append(secretKey);
        String s = MD5Util.Bit32(sign.toString(), "UTF-8");
        Map<String, Object> callbackParams = new HashMap<>();
        callbackParams.put("sign", s);
        callbackParams.put("orderNo", tPayOrder.getCustomerOrderNo());
        callbackParams.put("money", tPayOrder.getPayAmt());
        callbackParams.put("payState", tPayOrder.getPayStatus());
        Result result = new Result();
        result.setData(callbackParams);
        if (tPayOrder.getPayStatus().intValue() == 1) {
            callbackParams.put("flowNo", flowNo);
            callbackParams.put("payType", tPayOrder.getPayWay());
            callbackParams.put("payTime", tPayOrder.getPayTime());
            result.setMsg("充值成功");
            result.setCode(0);
        } else {
            result.setMsg("充值失败");
            result.setCode(1);
        }
        TCallbackMsgExample tCallbackMsgExample = new TCallbackMsgExample();
        tCallbackMsgExample.createCriteria().andOrderIdEqualTo(tPayOrder.getOrderId());
        tCallbackMsgExample.setOrderByClause("create_time desc");
        List<TCallbackMsg> tCallbackMsgs = tCallbackMsgMapper.selectByExample(tCallbackMsgExample);
        TCallbackMsg tCallbackMsg = new TCallbackMsg();
        tCallbackMsg.setMsgId(SequenceUtil.nextId());
        tCallbackMsg.setCreateTime(DateUtils.getShowDateTime());
        tCallbackMsg.setStatus(0);
        tCallbackMsg.setOrderId(tPayOrder.getOrderId());
        tCallbackMsg.setOrderMsg(JsonUtil.toJson(result));
        if (tCallbackMsgs == null || tCallbackMsgs.size() == 0) {
            tCallbackMsg.setCallbackNum(1);

        } else {
            TCallbackMsg lastCallbackMsg = tCallbackMsgs.get(0);
            if (lastCallbackMsg.getCallbackNum() < 3) {
                tCallbackMsg.setCallbackNum(lastCallbackMsg.getCallbackNum() + 1);
            }
        }
        if (tCallbackMsg.getCallbackNum() < 4) {
            tCallbackMsgMapper.insert(tCallbackMsg);

            try {
                String retStr = HttpClientUtils.postJSON(callbackUrl, JsonUtil.toJson(result));
                if ("ok".equals(retStr)) {
                    tCallbackMsg.setCallbackTime(DateUtils.getShowDateTime());
                    tCallbackMsg.setStatus(1);
                    tCallbackMsgMapper.updateByPrimaryKeyWithBLOBs(tCallbackMsg);
                } else {
                    tCallbackMsg.setStatus(2);
                    tCallbackMsgMapper.updateByPrimaryKeyWithBLOBs(tCallbackMsg);
                }
            } catch (Exception ex) {
                tCallbackMsg.setStatus(2);
                tCallbackMsgMapper.updateByPrimaryKeyWithBLOBs(tCallbackMsg);
                logger.error("==>回调异常:" + ex);
            }

            if (tCallbackMsg.getStatus().intValue() == 2) {
                try {
                    Thread.sleep(30000);
                    callbackOrder(tPayOrder.getOrderId(), appId, secretKey, flowNo);
                } catch (Exception ex) {
                    logger.error("线程睡眠异常", ex);
                }

            }
        }


    }

    @Async
    public void asyncHandelOrder(List orders) {
        if (orders != null && orders.size() > 0) {
            for (int i = 0; i < orders.size(); i++) {
                String orderData = String.valueOf(orders.get(i));
                String[] split = orderData.split("::");
                String orderId = split[0];
                long timeInMillis = Long.valueOf(split[1]);
                String systemNo = "";
                if (split.length == 3) {
                    systemNo = split[2];
                }
                TPayOrder tPayOrder = tPayOrderMapper.selectByPrimaryKey(orderId);
                String supplierId = tPayOrder.getSupplierId();
                String customerNo = tPayOrder.getCustomerNo();
                String appId = "";
                String secretKey = "";
                TCustomerExample tCustomerExample = new TCustomerExample();
                tCustomerExample.createCriteria().andCustomerNoEqualTo(customerNo);
                List<TCustomer> tCustomers = tCustomerMapper.selectByExample(tCustomerExample);
                String customerId = null;
                String customerName = "";
                if (tCustomers != null && tCustomers.size() > 0) {
                    TCustomer tCustomer = tCustomers.get(0);
                    customerId = tCustomer.getCustomerId();
                    customerName = tCustomer.getCustomerName();
                    appId = tCustomer.getAppId();
                    secretKey = tCustomer.getSecretKey();
                }

                TCustomerBindSupplierExample tCustomerBindSupplierExample = new TCustomerBindSupplierExample();
                tCustomerBindSupplierExample.createCriteria().andSupplierIdEqualTo(supplierId).andCustomerIdEqualTo(customerId);
                List<TCustomerBindSupplier> tCustomerBindSuppliers = tCustomerBindSupplierMapper.selectByExample(tCustomerBindSupplierExample);
                TQrCode tQrCode = null;
                if (tCustomerBindSuppliers != null && tCustomerBindSuppliers.size() > 0) {
                    TCustomerBindSupplier tCustomerBindSupplier = tCustomerBindSuppliers.get(0);
                    String qrCodeId = tCustomerBindSupplier.getQrCodeId();
                    tQrCode = tQrCodeMapper.selectByPrimaryKey(qrCodeId);
                }
                String key = getKey(tQrCode.getQrCodeId(), customerId, tQrCode.getCodeAmt());
                IGetOrder bean = SpringUtil.getBean(ConfReader.getAPIString(tQrCode.getChannelId()));
                String payAmt = String.valueOf(new BigDecimal(tPayOrder.getPayAmt()).divide(new BigDecimal(100)).doubleValue());
                if (System.currentTimeMillis() < timeInMillis) {//
                    if (tQrCode != null) {

                        List<StandardOrder> standardOrderList = bean.getOrder(payAmt, tPayOrder.getCreateTime(), systemNo, tQrCode);
//                        List<LakalaOrder> lakalaOrders = getLakalaOrder(tQrCode.getUserName(), tQrCode.getPassword(), payAmt, tPayOrder.getCreateTime(), systemNo);
                        CustomerBindQRCode customerBindQRCode = getCustomerBindQRCodeBiz.getCustomerBindQRCode(customerId, tCustomerBindSuppliers.get(0));
                        if (standardOrderList != null && standardOrderList.size() > 0) {
                            StandardOrder standardOrder = standardOrderList.get(standardOrderList.size() - 1);
                            int tranStatus = standardOrder.getPayStatus();
                            TPayOrder updatePayOrder = new TPayOrder();

                            if (tranStatus==Constants.PAY_SUCCESS) {//支付成功,将二维码放回队列
                                //TODO 修改代码redis二维码的限额
                                updateSuccessPayOrder(tPayOrder, customerId, customerBindQRCode, standardOrder, updatePayOrder);
                                //增加订单流水
                                TOrderFlow tOrderFlow = InsertOrderFlow(tPayOrder, supplierId, customerId, customerName);
                                //修改账户余额
                                updateCustomerAccountBiz.updateCustomerAccount(customerId, tPayOrder.getPayAmt(), 0);

                                //TODO 起一个异步线程去回调给网关
                                callbackOrder(tPayOrder.getOrderId(), appId, secretKey, tOrderFlow.getOrderFlowId());

                            } else if (tranStatus==Constants.WAIT_PAY) {//待支付

                                if (System.currentTimeMillis() < timeInMillis) {//将订单放回集合中
                                    redisTemplate.opsForSet().add(Constants.NO_PAY_ORDER_SET, tPayOrder.getOrderId() + "::" + timeInMillis + "::" + standardOrder.getSystemNo());
                                } else {
                                    //将订单状态改成取消
                                    //TODO  数据库修改订单状态,起一个异步线程去回调给网关
                                    updatePayOrder.setOrderId(tPayOrder.getOrderId());
                                    updatePayOrder.setPayStatus(3);
                                    updatePayOrder.setSupplierSystemNo(standardOrder.getSystemNo());
                                    tPayOrderMapper.updateByPrimaryKeySelective(tPayOrder);
                                    //将二维码放回队列
                                    redisTemplate.opsForList().leftPush(key, JsonUtil.toJson(customerBindQRCode));

                                    callbackOrder(tPayOrder.getOrderId(), appId, secretKey, null);
                                }
                            } else {//交易关闭
                                //TODO  数据库修改订单状态,并回调给网关
                                //将二维码放回队列

                                redisTemplate.opsForList().leftPush(key, JsonUtil.toJson(customerBindQRCode));
                                updatePayOrder.setOrderId(tPayOrder.getOrderId());
                                updatePayOrder.setPayStatus(3);
                                updatePayOrder.setSupplierSystemNo(standardOrder.getSystemNo());
                                tPayOrderMapper.updateByPrimaryKeySelective(tPayOrder);
                                callbackOrder(tPayOrder.getOrderId(), appId, secretKey, null);
                            }
                        } else {//说明啦 那里没有生成订单
                            if (System.currentTimeMillis() < timeInMillis) {//将订单放回集合中
                                redisTemplate.opsForSet().add(Constants.NO_PAY_ORDER_SET, tPayOrder.getOrderId() + "::" + timeInMillis);
                            } else {
                                //TODO  数据库修改订单状态取消,起一个异步线程去回调给网关
                                //将二维码放回队列
                                udapteFailOrder(tPayOrder, customerId, customerBindQRCode);
                                callbackOrder(tPayOrder.getOrderId(), appId, secretKey, null);
                            }
                        }
                    }
                } else {//超时了
                    if (tQrCode != null) {
                        CustomerBindQRCode customerBindQRCode = getCustomerBindQRCodeBiz.getCustomerBindQRCode(customerId, tCustomerBindSuppliers.get(0));
                        if (!StringUtils.isEmpty(systemNo)) {
                            List<StandardOrder> standardOrderList = bean.getOrder(payAmt, tPayOrder.getCreateTime(), systemNo, tQrCode);
//                            List<LakalaOrder> lakalaOrders = getLakalaOrder(tQrCode.getUserName(), tQrCode.getPassword(), payAmt, tPayOrder.getCreateTime(), systemNo);
                            if (standardOrderList != null && standardOrderList.size() > 0) {
                                StandardOrder standardOrder = standardOrderList.get(0);
                                int tranStatus = standardOrder.getPayStatus();
                                if (tranStatus==Constants.PAY_SUCCESS) {
                                    TPayOrder updatePayOrder = new TPayOrder();
                                    updateSuccessPayOrder(tPayOrder, customerId, customerBindQRCode, standardOrder, updatePayOrder);
                                    //TODO  起一个异步线程去回调给网关
                                    callbackOrder(tPayOrder.getOrderId(), appId, secretKey, null);
                                } else {
                                    redisTemplate.opsForList().leftPush(key, JsonUtil.toJson(customerBindQRCode));
                                    TPayOrder updatePayOrder = new TPayOrder();
                                    updatePayOrder.setOrderId(tPayOrder.getOrderId());
                                    updatePayOrder.setPayStatus(3);
                                    updatePayOrder.setSupplierSystemNo(standardOrder.getSystemNo());
                                    tPayOrderMapper.updateByPrimaryKeySelective(tPayOrder);
                                    //TODO  起一个异步线程去回调给网关
                                    callbackOrder(tPayOrder.getOrderId(), appId, secretKey, null);
                                }
                            }
                        } else {
                            udapteFailOrder(tPayOrder, customerId, customerBindQRCode);
                            //TODO  起一个异步线程去回调给网关
                            callbackOrder(tPayOrder.getOrderId(), appId, secretKey, null);
                        }
                    }

                }
            }

        }

    }


    private TOrderFlow InsertOrderFlow(TPayOrder tPayOrder, String supplierId, String customerId, String customerName) {
        TOrderFlow tOrderFlow = new TOrderFlow();
        tOrderFlow.setOrderFlowId(SequenceUtil.nextId());
        tOrderFlow.setCreateTime(DateUtils.getShowDateTime());
        tOrderFlow.setCustomerId(customerId);
        tOrderFlow.setFlowAmt(tPayOrder.getActualPayAmt());
        tOrderFlow.setCustomerName(customerName);
        tOrderFlow.setOrderId(tPayOrder.getOrderId());
        tOrderFlow.setSupplierId(supplierId);
        tOrderFlow.setSupplierName(tSupplierMapper.selectByPrimaryKey(supplierId).getSupplierName());
        tOrderFlowMapper.insert(tOrderFlow);
        return tOrderFlow;
    }

    private void udapteFailOrder(TPayOrder tPayOrder, String customerId, CustomerBindQRCode customerBindQRCode) {
        String key = getKey(customerBindQRCode.getQrCodeId(), customerId, tPayOrder.getPayAmt());
        redisTemplate.opsForList().leftPush(key, JsonUtil.toJson(customerBindQRCode));
        TPayOrder updatePayOrder = new TPayOrder();
        updatePayOrder.setOrderId(tPayOrder.getOrderId());
        updatePayOrder.setPayStatus(3);
        tPayOrderMapper.updateByPrimaryKeySelective(tPayOrder);
    }


    private void updateSuccessPayOrder(TPayOrder tPayOrder, String customerId, CustomerBindQRCode customerBindQRCode, StandardOrder standardOrder, TPayOrder updatePayOrder) {
        updatePayOrder.setOrderId(tPayOrder.getOrderId());
        updatePayOrder.setActualPayAmt(standardOrder.getPayAmt());
        updatePayOrder.setPayTime(standardOrder.getPayTime());
        updatePayOrder.setPayStatus(2);
        updatePayOrder.setPayWay(Integer.valueOf(standardOrder.getPayType()));
        updatePayOrder.setSupplierSystemNo(standardOrder.getSystemNo());
        tPayOrderMapper.updateByPrimaryKeySelective(tPayOrder);
        BigDecimal add = new BigDecimal(customerBindQRCode.getFlowTotalAmt()).add(new BigDecimal(tPayOrder.getActualPayAmt()));
        customerBindQRCode.setFlowTotalAmt(add.longValue() + "");

        String key = getKey(customerBindQRCode.getQrCodeId(), customerId, tPayOrder.getPayAmt());
//        String qrCodeId = customerBindQRCode.getQrCodeId();
//
//        TQrCode tQrCode = tQrCodeMapper.selectByPrimaryKey(qrCodeId);
//
//        StringBuilder key = new StringBuilder();
//        key.append(customerId).append(tQrCode.getChannelId());
//
//        TChannel tChannel = tChannelMapper.selectByPrimaryKey(tQrCode.getChannelId());
//
//        if(tChannel!=null && tChannel.getChannelType().intValue()==1){
//            key.append(tPayOrder.getPayAmt());
//        }

        redisTemplate.opsForList().leftPush(key, JsonUtil.toJson(customerBindQRCode));
        TQrCodeLimitAmtAdjustment tQrCodeLimitAmtAdjustment = new TQrCodeLimitAmtAdjustment();
        tQrCodeLimitAmtAdjustment.setQrCodeLimtAmtId(customerBindQRCode.getQrCodeLimitId());
        tQrCodeLimitAmtAdjustment.setFlowTotalAmt(Long.valueOf(customerBindQRCode.getFlowTotalAmt()));
        tQrCodeLimitAmtAdjustmentMapper.updateByPrimaryKeySelective(tQrCodeLimitAmtAdjustment);
    }

    private String getKey(String qrCodeId, String customerId, long amt) {

        TQrCode tQrCode = tQrCodeMapper.selectByPrimaryKey(qrCodeId);

        StringBuilder key = new StringBuilder();
        key.append(customerId).append(tQrCode.getChannelId());

        TChannel tChannel = tChannelMapper.selectByPrimaryKey(tQrCode.getChannelId());

        if (tChannel != null && tChannel.getChannelType().intValue() == 1) {
            key.append(amt);
        }
        return key.toString();
    }



    private void updateOrderStauts(TPayOrder tPayOrder) {
        tPayOrderMapper.updateByPrimaryKeySelective(tPayOrder);
    }



//
//    private String getEndTime(String startTime) {
//        try {
//            SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            Date d = time.parse(startTime);
//            Date afterDate = new Date(d.getTime() + 200000);//后3分钟
//            return time.format(afterDate);
//        } catch (Exception ex) {
//            logger.error("时间解析异常", ex);
//        }
//        return null;
//    }

    public static void main(String[] args) throws Exception {
        SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = time.parse("2019-08-14 00:22:33");
        Date afterDate = new Date(d.getTime() + 120000);
        System.out.println(time.format(afterDate));
    }

}